using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using OhioState.AssetManaged;
using OhioState.Graphics.Proxy;
using OhioState.Math;

namespace OhioState.Controls
{
    //
    // TransferFunctionManager - A control that combines the gradient editor control
    //  and the asset manager data grid view control.  It allows you to view the 
    //  transfer functions stored in the asset manager, rename them, and select them
    //  to be modified with the gradient control.  This also has file functionalities and
    //  gives uses an interface for opening and saving transfer functions to a file.
    //  It also allows the user to create new transfer functions and remove transfer functions
    //  from the asset manager.
    //
    public partial class TransferFunctionManager : UserControl
    {
        //
        // Pointer to the instance of the asset manager
        //
        AssetManager assetMan;

        //
        // List of templates
        //
        List<TransferFunction> templates;

        //
        // Event to trigger invalidate
        //
        public event IAssetManagedHandler ChangedEvent;
        //
        // Event for monitoring changes of the current transfer function
        //
        IAssetManagedHandler updateEvent;
        private TransferFunction transFunc;

        //
        // Event helper for firing events
        //
        protected EventsStrategyAbstract _eventsHelper;

        //
        // Constructor sets up all the object and events
        //
        public TransferFunctionManager()
        {
            InitializeComponent();

            //
            // Get a pointer to the instance of the asset manager and create templates list
            //
            assetMan = AssetManager.Instance;
            templates = new List<TransferFunction>();
            _eventsHelper = new EventsStrategyAsync();
            transFunc = null;

            //
            // Set up event handler for selection changed event
            //
            assetManagerControl.SelectedEvent += new IAssetManagedListHandler(assetManagerControl_SelectedEvent);
            assetManagerControl.UpdatedEvent += new IAssetManagedHandler(assetManagerControl_UpdatedEvent);

            //
            // Initialize the control
            //
            //assetManagerControl.Init(typeof(TransferFunction));
            List<Type> types = new List<Type>();
            types.Add(typeof(TransferFunction));
            assetManagerControl.Init(types);

            //
            // Create default transfer functions
            //
            SetupDefaultTransferFunctions();

            //
            // Set up the drop down for the templates
            //
            BuiltTemplateDropDown();

            //
            // correct the size of the gradient control
            SizeGradientControl();
        }

        #region Setup Default Transfer Functions
        //
        // Create the set of default transfer functions and load them into the asset manager
        //
        private void SetupDefaultTransferFunctions()
        {
            // Hue
            TransferFunction transFunc = new TransferFunction("Hue", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 1.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Gray
            transFunc = new TransferFunction("Gray", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 1.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Discrete
            transFunc = new TransferFunction("Discrete", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 0.9f, 0.9f, 0.9f));
            transFunc.AddColorKnot(new ColorKnot(0.875f, 0.9f, 0.9f, 0.9f));
            transFunc.AddColorKnot(new ColorKnot(0.8749f, 0.95f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.75f, 0.95f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.7499f, 0.8f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.625f, 0.8f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.6249f, 0.0f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.5f, 0.0f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.4999f, 0.0f, 0.6f, 0.6f));
            transFunc.AddColorKnot(new ColorKnot(0.375f, 0.0f, 0.6f, 0.6f));
            transFunc.AddColorKnot(new ColorKnot(0.3749f, 0.0f, 0.0f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(0.25f, 0.0f, 0.0f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(0.2499f, 0.5f, 0.0f, 0.5f));
            transFunc.AddColorKnot(new ColorKnot(0.125f, 0.5f, 0.0f, 0.5f));
            transFunc.AddColorKnot(new ColorKnot(0.1249f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Ramps
            transFunc = new TransferFunction("Ramps", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 1.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(6.0f / 7.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(6.0f / 7.0f - 0.0001f, 1.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(5.0f / 7.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(5.0f / 7.0f - 0.0001f, 1.0f, 1.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(4.0f / 7.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(4.0f / 7.0f - 0.0001f, 0.0f, 1.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(3.0f / 7.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(3.0f / 7.0f - 0.0001f, 0.0f, 1.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(2.0f / 7.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(2.0f / 7.0f - 0.0001f, 0.0f, 0.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(1.0f / 7.0f, 0.0f, 0.0f, 0.05f));
            transFunc.AddColorKnot(new ColorKnot(1.0f / 7.0f - 0.0001f, 1.0f, 0.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Hue Weight
            transFunc = new TransferFunction("Hue Weight", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(15.0f / 16.0f, 1.0f, 0.25f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(15.0f / 16.0f - 0.0001f, 0.95f, 0.95f * 0.25f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(14.0f / 16.0f, 0.95f, 0.95f * 0.5f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(14.0f / 16.0f - 0.0001f, 0.9f, 0.9f * 0.5f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(13.0f / 16.0f, 0.9f, 0.9f * 0.75f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(13.0f / 16.0f - 0.0001f, 0.85f, 0.85f * 0.75f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(12.0f / 16.0f, 0.85f, 0.85f, 0.0f));

            transFunc.AddColorKnot(new ColorKnot(12.0f / 16.0f - 0.0001f, 0.8f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(11.0f / 16.0f, 0.8f * 0.75f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(11.0f / 16.0f - 0.0001f, 0.75f * 0.75f, 0.75f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(10.0f / 16.0f, 0.75f * 0.5f, 0.75f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(10.0f / 16.0f - 0.0001f, 0.7f * 0.5f, 0.7f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(9.0f / 16.0f, 0.7f * 0.25f, 0.7f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(9.0f / 16.0f - 0.0001f, 0.65f * 0.25f, 0.65f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(8.0f / 16.0f, 0.0f, 0.65f, 0.0f));

            transFunc.AddColorKnot(new ColorKnot(8.0f / 16.0f - 0.0001f, 0.0f, 0.6f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(7.0f / 16.0f, 0.0f, 0.6f, 0.6f * 0.25f));
            transFunc.AddColorKnot(new ColorKnot(7.0f / 16.0f - 0.0001f, 0.0f, 0.55f, 0.55f * 0.25f));
            transFunc.AddColorKnot(new ColorKnot(6.0f / 16.0f, 0.0f, 0.55f, 0.55f * 0.5f));
            transFunc.AddColorKnot(new ColorKnot(6.0f / 16.0f - 0.0001f, 0.0f, 0.5f, 0.5f * 0.5f));
            transFunc.AddColorKnot(new ColorKnot(5.0f / 16.0f, 0.0f, 0.5f, 0.5f * 0.75f));
            transFunc.AddColorKnot(new ColorKnot(5.0f / 16.0f - 0.0001f, 0.0f, 0.45f, 0.45f * 0.75f));
            transFunc.AddColorKnot(new ColorKnot(4.0f / 16.0f, 0.0f, 0.45f, 0.45f));

            transFunc.AddColorKnot(new ColorKnot(4.0f / 16.0f - 0.0001f, 0.0f, 0.4f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(3.0f / 16.0f, 0.0f, 0.4f * 0.75f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(3.0f / 16.0f - 0.0001f, 0.0f, 0.35f * 0.75f, 0.35f));
            transFunc.AddColorKnot(new ColorKnot(2.0f / 16.0f, 0.0f, 0.35f * 0.5f, 0.35f));
            transFunc.AddColorKnot(new ColorKnot(2.0f / 16.0f - 0.0001f, 0.0f, 0.3f * 0.5f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(1.0f / 16.0f, 0.0f, 0.3f * 0.25f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(1.0f / 16.0f - 0.0001f, 0.0f, 0.25f * 0.25f, 0.25f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.25f));

            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Hue Desaturated
            transFunc = new TransferFunction("Hue Desaturated", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 183.0f / 255.0f, 61.0f / 255.0f, 61.0f / 255.0f));
            transFunc.AddColorKnot(new ColorKnot(0.75f, 118.0f / 255.0f, 118.0f / 255.0f, 39.0f / 255.0f));
            transFunc.AddColorKnot(new ColorKnot(0.5f, 37.0f / 255.0f, 112.0f / 255.0f, 37.0f / 255.0f));
            transFunc.AddColorKnot(new ColorKnot(0.25f, 25.0f / 255.0f, 75.0f / 255.0f, 75.0f / 255.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 23.0f / 255.0f, 23.0f / 255.0f, 69.0f / 255.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Gray Smooth Discrete
            transFunc = new TransferFunction("Gray Smooth Discrete", false);
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.4999f, 0.6f, 0.6f, 0.6f));

            transFunc.AddColorKnot(new ColorKnot(0.5f, 0.65f, 0.65f, 0.65f));
            transFunc.AddColorKnot(new ColorKnot(9.0f / 16.0f - 0.0001f, 0.65f, 0.65f, 0.65f));
            transFunc.AddColorKnot(new ColorKnot(9.0f / 16.0f, 0.7f, 0.7f, 0.7f));
            transFunc.AddColorKnot(new ColorKnot(10.0f / 16.0f - 0.0001f, 0.7f, 0.7f, 0.7f));
            transFunc.AddColorKnot(new ColorKnot(10.0f / 16.0f, 0.75f, 0.75f, 0.75f));
            transFunc.AddColorKnot(new ColorKnot(11.0f / 16.0f - 0.0001f, 0.75f, 0.75f, 0.75f));
            transFunc.AddColorKnot(new ColorKnot(11.0f / 16.0f, 0.8f, 0.8f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(12.0f / 16.0f - 0.0001f, 0.8f, 0.8f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(12.0f / 16.0f, 0.85f, 0.85f, 0.85f));
            transFunc.AddColorKnot(new ColorKnot(13.0f / 16.0f - 0.0001f, 0.85f, 0.85f, 0.85f));
            transFunc.AddColorKnot(new ColorKnot(13.0f / 16.0f, 0.9f, 0.9f, 0.9f));
            transFunc.AddColorKnot(new ColorKnot(14.0f / 16.0f - 0.0001f, 0.9f, 0.9f, 0.9f));
            transFunc.AddColorKnot(new ColorKnot(14.0f / 16.0f, 0.95f, 0.95f, 0.95f));
            transFunc.AddColorKnot(new ColorKnot(15.0f / 16.0f - 0.0001f, 0.95f, 0.95f, 0.95f));
            transFunc.AddColorKnot(new ColorKnot(15.0f / 16.0f, 1.0f, 1.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 1.0f, 1.0f));

            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Blue Yellow
            transFunc = new TransferFunction("Blue Yellow", false);
            transFunc.HSV = false;
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 0.8f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 1.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Red Yellow White
            transFunc = new TransferFunction("Red Yellow White", false);
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 1.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.67f, 1.0f, 1.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.33f, 1.0f, 0.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);

            // Blue Yellow Discrete
            transFunc = new TransferFunction("Blue Yellow Discrete", false);
            transFunc.AddColorKnot(new ColorKnot(0.0f, 0.0f, 0.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.1249f, 0.0f, 0.0f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.125f, 0.5f, 0.5f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.2499f, 0.5f, 0.5f, 1.0f));
            transFunc.AddColorKnot(new ColorKnot(0.25f, 0.6f, 0.6f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(0.3749f, 0.6f, 0.6f, 0.8f));
            transFunc.AddColorKnot(new ColorKnot(0.375f, 0.3f, 0.3f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(0.4999f, 0.3f, 0.3f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(0.5f, 0.3f, 0.3f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(0.6249f, 0.3f, 0.3f, 0.3f));
            transFunc.AddColorKnot(new ColorKnot(0.625f, 0.7f, 0.7f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(0.7499f, 0.7f, 0.7f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(0.75f, 0.9f, 0.9f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(0.8749f, 0.9f, 0.9f, 0.4f));
            transFunc.AddColorKnot(new ColorKnot(0.875f, 1.0f, 1.0f, 0.0f));
            transFunc.AddColorKnot(new ColorKnot(1.0f, 1.0f, 1.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(0.0f, 0.0f));
            transFunc.AddAlphaKnot(new AlphaKnot(1.0f, 0.25f));
            templates.Add(transFunc);
        }
        #endregion

        #region Public properties

        //
        // Public property to set the orientation - vertical or horizontal
        //
        public Orientation Orientation
        {
            get { return splitContainer1.Orientation; }
            set
            {
                splitContainer1.Orientation = value;
                SizeGradientControl();
            }
        }

        //
        // Public properties to control the Gradient Controls public properties
        //
        public Color GradientControlArrowColor
        {
            get { return gradientControl.ArrowColor; }
            set { gradientControl.ArrowColor = value; }
        }
        public int GradientControlArrowHeight
        {
            get { return gradientControl.ArrowHeight; }
            set
            {
                gradientControl.ArrowHeight = value;
                SizeGradientControl();
            }
        }
        public int GradientControlArrowWidth
        {
            get { return gradientControl.ArrowWidth; }
            set
            {
                gradientControl.ArrowWidth = value;
                SizeGradientControl();
            }
        }
        public int GradientControlBarHeight
        {
            get { return gradientControl.BarHeight; }
            set
            {
                gradientControl.BarHeight = value;
                SizeGradientControl();
            }
        }
        public int GradientControlPadding
        {
            get { return gradientControl.Padding; }
            set
            {
                gradientControl.Padding = value;
                SizeGradientControl();
            }
        }
        //
        // sets the size of the gradient control when the properties are changed
        //
        private void SizeGradientControl()
        {
            if (splitContainer1.Orientation == Orientation.Horizontal)
            {
                splitContainer1.SplitterDistance = splitContainer1.Size.Height - (2 * (GradientControlArrowHeight + GradientControlArrowWidth + GradientControlBarHeight + GradientControlPadding + splitContainer1.SplitterWidth) + 7);
                splitContainer1.IsSplitterFixed = true;
                splitContainer1.FixedPanel = FixedPanel.Panel2;
            }
            else if (splitContainer1.Orientation == Orientation.Vertical)
            {
                splitContainer1.SplitterDistance = splitContainer1.Size.Width / 2;
                splitContainer1.IsSplitterFixed = false;
                splitContainer1.FixedPanel = FixedPanel.None;
            }
        }

        #endregion

        //
        // Setup the drop down list of all templates
        //  Clear the Drop down menu and then add each item from the template list to the
        //  drop down menu.  Create preview icons as well.
        //
        private void BuiltTemplateDropDown()
        {
            newToolStripButton.DropDownItems.Clear();

            foreach (TransferFunction obj in templates)
            {
                Bitmap b = new Bitmap(16, 16);
                obj.Preview(b);
                newToolStripButton.DropDownItems.Add(obj.Name, b, CreateNewFromTemplate);
            }
        }

        //
        // Gets a transfer function from the template list given its name
        //  or returns null if it doesn't exist.
        //
        private TransferFunction GetTemplate(String name)
        {
            foreach (TransferFunction transFunc in templates)
            {
                if (transFunc.Name == name)
                {
                    return transFunc;
                }
            }
            return null;
        }

        //
        // Event handler for Template Drop down clicks
        //  Find the transfer function that corresponds to the drop down item,
        //  clone it and add it to the asset manager.
        //
        public void CreateNewFromTemplate(Object sender, EventArgs e)
        {
            if (sender.GetType() == typeof(ToolStripMenuItem))
            {
                String name = ((ToolStripMenuItem)sender).Text;
                TransferFunction transFunc = GetTemplate(name);
                if (transFunc != null)
                {
                    IAssetManaged obj = assetMan.Add(transFunc.Clone());
                }
            }
        }

        //
        // Event handler for selection changed event
        //  This changes the transfer function that the gradient control currently controls
        //
        public void assetManagerControl_SelectedEvent(IList<IAssetManaged> items)
        {
            //
            // Unsubscribe from the update event of the old transfer function
            // Subscribe to the update event of the new transfer function
            //
            if (transFunc != null)
            {
                transFunc.RemoveChangingEventHandler(updateEvent);
            }
            if (items.Count > 0)
            {
                transFunc = (TransferFunction)items[0];
                gradientControl.ControlNewTransFunc(transFunc);
                updateEvent = new IAssetManagedHandler(transFunc_UpdatedEvent);
                transFunc.AddChangingEventHandler(updateEvent);
                transFunc.AddChangedEventHandler(updateEvent);
            }
            updatePreintegratedTFcheckBox();
        }

        //
        // Event handler for item updated event.  This is fire an event to tell
        //  the opengl panel to be invalidated.
        //
        public void assetManagerControl_UpdatedEvent(IAssetManaged obj)
        {
            _eventsHelper.Fire(ChangedEvent, obj);
        }
        public void transFunc_UpdatedEvent(IAssetManaged obj)
        {
            if (previewCheckBox.Checked)
            {
                _eventsHelper.Fire(ChangedEvent, obj);
            }
        }

        //
        // Open button - calls a dialog to open a file that contains a transfer function,
        //  and adds it to the asset manager.  If there is a name,type collision then the new
        //  object does not get added.  Instead the object that already exists gets selected
        //
        private void openButton_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                TransferFunction transFunc = TransferFunction.LoadFromFile(openFileDialog.FileName);
                if (transFunc != null)
                {
                    IAssetManaged obj = assetMan.Add(transFunc);
                    // check for duplicate
                    if (obj == transFunc)
                    {
                        // add the new item to the template list and the template drop down if it doesn't
                        //  already exist
                        if (GetTemplate(transFunc.Name) == null)
                        {
                            templates.Add((TransferFunction)obj);
                            BuiltTemplateDropDown();
                        }
                    }
                }
            }
        }

        //
        // Save button - saves the currently selected transfer function to a file.
        //
        private void saveButton_Click(object sender, EventArgs e)
        {
            if (assetManagerControl.GetSelected().Count > 0)
            {
                TransferFunction obj = (TransferFunction)assetManagerControl.GetSelected()[0];
                // No more filename assistance
                /*String filename = assetMan.GetFilename(obj);
                if (filename != null)
                {
                    saveFileDialog.FileName = filename;
                }
                else
                {
                    saveFileDialog.FileName = obj.Name;
                }*/
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    obj.SaveToFile(saveFileDialog.FileName);
                }
            }
        }

        //
        // New button - Create a new transfer function for the user to edit
        //
        private void newButton_Click(object sender, EventArgs e)
        {
            TransferFunction transFunc;
            if (assetManagerControl.GetSelected().Count > 0)
            {
                transFunc = (TransferFunction)((TransferFunction)assetManagerControl.GetSelected()[0]).Clone();
                transFunc.SetName(transFunc.Name + " Copy");
            }
            else
            {
                transFunc = new TransferFunction("Untitled", true);
            }
            IAssetManaged obj = assetMan.Add(transFunc);
        }

        //
        // Remove button - remove the currently selected transfer function from the asset
        // manager. 
        //
        private void removeButton_Click(object sender, EventArgs e)
        {
            List<IAssetManaged> list = assetManagerControl.GetSelected();
            foreach(IAssetManaged obj in list)
            {
                removePreintegratedTF(obj);
                assetMan.Remove(obj);
            }
        }


        //the next few methods deal with creating and managing of preintegrated
        //transfer functions - they are stored as 2D textures;
        //we use the following names for pre-integrated transfer functions:
        //the name of the original tf + "-Integrated"
        public event CreatedPreintegratedTF createdPreintegratedTFEvent;
        public delegate void CreatedPreintegratedTF(IAssetManaged tf);
        private void createPreIntegratedTFBoxClicked(object sender, EventArgs e)
        {
            if (transFunc == null)
            {
                preIntegratedTFcheckBox.Checked = false;
                return;
            }
            if (AssetManager.Instance.Find(typeof(TexImage), transFunc.Name + "-Integrated") == null 
                && preIntegratedTFcheckBox.Checked == true)
            {
                preIntegratedTFcheckBox.Checked = true;
                createdPreintegratedTFEvent.Invoke(transFunc);
            }
        }

        private void updatePreintegratedTFcheckBox()
        {
            if (transFunc == null) return;

            //if there is no corresponding pre-integrated transfer function,
            //check box should be unchecked. Otherwise, keep it checked

            if (AssetManager.Instance.Find(typeof(TexImage), transFunc.Name + "-Integrated") == null)
                preIntegratedTFcheckBox.Checked = false;
            else
                preIntegratedTFcheckBox.Checked = true;
        }

        private void removePreintegratedTF(IAssetManaged oneDimTransferFunc)
        {
            IAssetManaged toRemove = AssetManager.Instance.Find(typeof(TexImage), 
                oneDimTransferFunc.Name + "-Integrated");
            if (toRemove == null) 
                return;
            AssetManager.Instance.Remove(toRemove);
        }
    }
}